/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						 wave_stream.cpp

	$Header: /resource_editor/windows_file.cpp $

	$NoKeywords: $

 ************************************************************************/

// kill the 255+ character identifier warning.  Templates tend to exceed that easily.
#include "precompiled.h"
#pragma warning( disable: 4786 )

#include "os_file.h"
#include "assert.h"

// -------------------------------------------------------------
// windows file class wrapps windows specific file functions
// -------------------------------------------------------------

t_os_file::t_os_file()
{
	m_file_state	= k_file_closed;
	m_file_handle	= INVALID_HANDLE_VALUE;
}

t_os_file::~t_os_file()
{
	close();
}

bool t_os_file::open( const char *filename, const char *mode )
{
	close();

	LPCTSTR lpFileName =	filename;				// file name
	DWORD dwDesiredAccess;							// access mode
	DWORD dwShareMode;								// share mode
	SECURITY_ATTRIBUTES SecurityAttributes;			// SD
	DWORD dwCreationDisposition;					// how to create
	DWORD dwFlagsAndAttributes;						// file attributes
	HANDLE hTemplateFile;							// handle to template file
	
	assert(mode != NULL && filename != NULL);
	
	if (strstr(mode,"r")!=0)
		dwDesiredAccess = GENERIC_READ;
	
	
	if (strstr(mode,"w")!=0)
		dwDesiredAccess = GENERIC_WRITE;
	
	//have to allow other resources within the program the ability to open up the file
	dwShareMode = FILE_SHARE_READ|FILE_SHARE_WRITE;

	SecurityAttributes.bInheritHandle = FALSE;
	SecurityAttributes.lpSecurityDescriptor = NULL;
	SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
	
	if (strstr(mode,"w+")!=0)
		dwCreationDisposition = OPEN_ALWAYS;
	else
		dwCreationDisposition = OPEN_EXISTING;
	
	dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL|FILE_FLAG_RANDOM_ACCESS;
	
	hTemplateFile = NULL;
	
	HANDLE result = CreateFile(
		lpFileName,								// file name
		dwDesiredAccess,						// access mode
		dwShareMode,							// share mode
		&SecurityAttributes,					// SD
		dwCreationDisposition,					// how to create
		dwFlagsAndAttributes,					// file attributes
		hTemplateFile							// handle to template file
		);
	
	if (result == INVALID_HANDLE_VALUE)
	{
		return false;
	}

	m_file_state	= k_file_opened;
	m_file_handle	= result;
	
	return true;
}

bool t_os_file::close( )
{
	HANDLE hObject = m_file_handle;
	
	if (m_file_state == k_file_opened)
	{
		BOOL rval = CloseHandle(
			hObject   // handle to object
			);
		
		if (rval == 0)
		{
			//error handle could not be closed

			return false;
		}
	}
	
	m_file_state	= k_file_closed;
	m_file_handle	= INVALID_HANDLE_VALUE;
	
	return true;
}

t_int32		t_os_file::filesize( )
{
	HANDLE hFile = m_file_handle;				// handle to file
	
	DWORD result = GetFileSize(
		hFile,				// handle to file
		NULL				// high-order word of file size
		);
	
	if (result == -1) 
	{ 
		//error failed to get size
		
		return -1;
    } 
	
	return result;
}

t_int32		t_os_file::seek( long offset, int origin )
{  
	HANDLE hFile = m_file_handle;       // handle to file
	LONG lDistanceToMove;				// bytes to move pointer
	PLONG lpDistanceToMoveHigh;			// bytes to move pointer
	DWORD dwMoveMethod ;				// starting point
	
	lDistanceToMove = offset;
	
	lpDistanceToMoveHigh = NULL;
	
	switch (origin)
	{
	case SEEK_CUR:
		dwMoveMethod = FILE_CURRENT;
		break;
		
	case SEEK_END:
		dwMoveMethod = FILE_END;
		break;
		
	case SEEK_SET:
		dwMoveMethod = FILE_BEGIN; 
		break;
		
	default:
		return -1;
		break;
	};
	
	DWORD result = SetFilePointer(
		hFile,						// handle to file
		lDistanceToMove,			// bytes to move pointer
		lpDistanceToMoveHigh,		// bytes to move pointer
		dwMoveMethod				// starting point
		);
		
	if (result == (DWORD)-1)
	{
		//error occured
		
		//fseek error value is a return of non-zero.

		return 1;
    } 
	
	return 0;
}

t_uint32	t_os_file::read( void *buffer, t_uint32 size, t_uint32 count)
{
	
	HANDLE hFile = m_file_handle;               // handle to file
	LPVOID lpBuffer;							// data buffer
	DWORD nNumberOfBytesToRead;					// number of bytes to read
	DWORD NumberOfBytesRead;					// number of bytes read
	LPOVERLAPPED lpOverlapped;					// overlapped buffer
	
	lpBuffer = buffer;
	
	nNumberOfBytesToRead = size*count;
	
	NumberOfBytesRead = 0;
	
	lpOverlapped = NULL;
	
	BOOL result = ReadFile(
		hFile,					// handle to file
		lpBuffer,				// data buffer
		nNumberOfBytesToRead,   // number of bytes to read
		&NumberOfBytesRead,		// number of bytes read
		lpOverlapped			// overlapped buffer
		);
	
	if (result == 0) 
	{ 
		//error occured
    } 
	
	return NumberOfBytesRead;
}

t_uint32	t_os_file::write( const void *buffer, t_uint32 size, t_uint32 count)
{
	HANDLE hFile = m_file_handle;                   // handle to file
	LPCVOID lpBuffer;								// data buffer
	DWORD nNumberOfBytesToWrite;					// number of bytes to write
	DWORD NumberOfBytesWritten;						// number of bytes written
	LPOVERLAPPED lpOverlapped;						// overlapped buffer
	
	lpBuffer = buffer;
	
	nNumberOfBytesToWrite = size*count;
	
	NumberOfBytesWritten = 0;
	
	lpOverlapped = NULL;
	
	BOOL result = WriteFile(
		hFile,						// handle to file
		lpBuffer,					// data buffer
		nNumberOfBytesToWrite,		// number of bytes to write
		&NumberOfBytesWritten,		// number of bytes written
		lpOverlapped				// overlapped buffer
		);
	
	if (result == 0) 
	{ 
		//error occured
    } 
	
	return NumberOfBytesWritten;
}

char *	t_os_file::get_file_handle()
{ 
	return static_cast < char* > (m_file_handle);
}
